#include <mips/regdef.h>
#include <sys/syscall.h>
#define stdinfd 	0
#define stdoutfd 	1
#ifndef 	fp
#define	fp	$fp
#endif
#define REALLOC_SSIZE	(64)
#define	REALLOC_RA		(56)
#define	REALLOC_FP		(52)
#define	REALLOC_GP		(48)
#define REALLOC_S4		(36)
#define REALLOC_S3		(32)
#define REALLOC_S2		(28)
#define REALLOC_S1		(24)
#define REALLOC_S0		(20)
#define REALLOC_ARG0	(REALLOC_SSIZE)
#define REALLOC_ARG1	((REALLOC_SSIZE)+4)
#define REALLOC_ARG2	((REALLOC_SSIZE)+8)

#Parámetros:
#a0: puntero original
#a1: tamaño viejo en bytes
#a2: tamaño nuevo
#v0: nuevo vector, en caso de ser menor el nuevo tamaño
#	se retorna 0.
#Uso de variables:
#s0: puntero original
#s1: tamaño viejo en bytes
#s2: puntero retorno
#s3: indice en número de byte
#s4: tamaño nuevo en bytes
	.text
	.align 	2
	.globl	realloc
	.ent	realloc
realloc:
   	.frame fp,REALLOC_SSIZE,ra
   	.set  noreorder
   	.cpload  t9
   	.set  reorder
	subu	sp,sp,REALLOC_SSIZE
	.cprestore 16
	sw		s4,REALLOC_S4(sp)
	sw		s3,REALLOC_S3(sp)
	sw		s2,REALLOC_S2(sp)
	sw		s1,REALLOC_S1(sp)
	sw		s0,REALLOC_S0(sp)
	sw		ra,REALLOC_RA(sp)
	sw		fp,REALLOC_FP(sp)
	sw		gp,REALLOC_GP(sp)
	move	fp,sp
	sw		a0,REALLOC_ARG0(fp)
	sw		a1,REALLOC_ARG1(fp)
	sw		a2,REALLOC_ARG2(fp)
	lw		a0,REALLOC_ARG0(fp)
	lw		a1,REALLOC_ARG1(fp)
	lw		a2,REALLOC_ARG2(fp)
	#s0: puntero original
	#s1: tamaño viejo en bytes
	#s2: puntero retorno
	#s4: tamaño nuevo en bytes
	addu	s0,a0,zero
	addu	s1,zero,a1
	addu	s2,zero,zero
	addu	s4,a2,zero
	addu	v0,zero,zero
	#se chequea que el tamaño nuevo sea mayor que el viejo
	bge		s1,s4,falla_realloc
	#reservo memoria para el vector salida
	addu	a0,s4,zero
	la      t9,mymalloc
    jal     ra,t9
    beq		v0,zero,falla_realloc
    #seteo el retorno
    addu	s2,v0,zero
    #copio el contenido del original al vector salida
    #s3: indice en número de byte
    addu	s3,zero,zero
loop:
	bge		s3,s1,fin_loop
	addu	t0,s0,s3 # t0 = viejo + indice
	lb		t1,0(t0) # t1 = viejo[indice]
	addu	t0,s2,s3 # t0 = nuevo + indice
	sb		t1,0(t0) # nuevo[indice] = viejo[indice]
	addiu	s3,s3,1
	b 		loop
fin_loop:
	#elimino el original
	addu	a0,s0,zero
	la		t9,myfree
	jal		t9
	#pongo el puntero nuevo en salida
	addu	v0,zero,s2
	b		fin_realloc
falla_realloc:
	addu	v0,s1,zero
fin_realloc:
	move	sp,fp		# destruyo stack frame
	lw		s0,REALLOC_S0(sp)
	lw		s1,REALLOC_S1(sp)
	lw		s2,REALLOC_S2(sp)
	lw		s3,REALLOC_S3(sp)
	lw		s4,REALLOC_S4(sp)
	lw		gp,REALLOC_GP(sp)
	lw		fp,REALLOC_FP(sp)
	lw		ra,REALLOC_RA(sp)
	addiu	sp,sp,REALLOC_SSIZE
	j		ra
	.end	realloc
